import json
import traceback
from django.http import JsonResponse
from django.views.generic import View
from ..serializers.unitSetSerializer import *
from django.db.models import Q
from django.core.paginator import Paginator
from utils.encryptionAndDecryptionUtil import get_user_from_useraccount, get_useraccount_from_request
from ..config.message_config import *
from ..utils.common_util.basic_util import get_order_list_combined
from django.db import IntegrityError, transaction
from ..utils.related_util.content_util import get_unit_set_by_unitset
from utils.responseContentUtil import *


class UnitSetView(View):
    def get(self, request):
        res = {"code": 400, "message": "", "data": None}
        try:
            data = request.GET
            query_serializer = UnitSetListQuerySerializer(data=data)
            data_valid = query_serializer.is_valid()
            if not data_valid:
                return make_get_error_response(message=query_serializer.errors)
            data = query_serializer.validated_data
            query = Q()
            query &= Q(valid_flag=True)
            if "unit_set_name" in data:
                query &= (Q(unit_set_name__icontains=data["unit_set_name"]) | Q(
                    unit_set_name_en__icontains=data["unit_set_name"]))
            order_list_combined = get_order_list_combined(data)
            if len(order_list_combined) == 0:
                unit_sets = UnitSet.objects.filter(
                    query).order_by("-create_date")
            else:
                unit_sets = UnitSet.objects.filter(
                    query).order_by(*order_list_combined)
            page_size = data["page_size"]
            current_page = data["current_page"]
            total_count = unit_sets.count()
            paginator = Paginator(unit_sets, page_size)
            if current_page > paginator.num_pages:
                current_page = paginator.num_pages
            page_obj = paginator.get_page(current_page)
            res_data = {}
            res_data["current_page"] = current_page
            res_data["page_size"] = page_size
            res_data["total_count"] = total_count
            unitset_list_serializer = UnitSetListSerializer(
                page_obj, many=True)
            res_data["objects"] = unitset_list_serializer.data
            return make_get_success_response(data=res_data)
        except Exception as e:
            traceback.print_exc()
            return make_server_error_response(str(e))

    def post(self, request):
        res = {"code": 400, "message": "", "data": None}
        try:
            user_name = get_useraccount_from_request(request=request)
            user_name = get_user_from_useraccount(user_name)
            data = json.loads(request.body)
            create_serializer = UnitSetCreateSerializer(data=data)
            if not create_serializer.is_valid():
                res["code"] = 400
                res_message = "参数错误:\n"
                if "unit_set_name" in create_serializer.errors:
                    res_message += "单位集中文名称已存在;\n"
                if "unit_set_name_en" in create_serializer.errors:
                    res_message += "单位集英文名称已存在;\n"
                return make_create_error_response(message=res_message)
            data = create_serializer.validated_data
            if "origin_unit_set" in data:
                data["origin_unit_set"] = UnitSet.objects.filter(
                    uuid=data["origin_unit_set"], valid_flag=True).first()
            if "unitsetcontent" in data:
                unitsetcontent_data = data.pop("unitsetcontent")
            else:
                unitsetcontent_data = []
            try:
                with transaction.atomic():
                    unitset = UnitSet.objects.create(
                        **data, create_person=user_name, modify_person=user_name)
                    for content in unitsetcontent_data:
                        UnitSetContent.objects.create(
                            unit_set=unitset,
                            quantity=Quantity.objects.filter(
                                uuid=content, valid_flag=True).first(),
                            unit=Unit.objects.filter(
                                uuid=unitsetcontent_data[content][-1], valid_flag=True).first(),
                        )
            except IntegrityError as e:
                return make_create_error_response(message=str(e))
            return make_create_success_response()
        except Exception as e:
            traceback.print_exc()
            return make_server_error_response(str(e))


class UnitSetInfoView(View):
    def get(self, request, uuid):
        res = {"code": 400, "message": "", "data": None}
        try:
            get_params = request.GET
            info_get_type = get_params.get("type", "")
            data = {}
            if info_get_type == "create":
                unit_set = UnitSet.objects.filter(
                    uuid=uuid, valid_flag=True).first()
                if not unit_set:
                    return make_get_error_response(message="单位集不存在")
                unit_set_choice = get_unit_set_by_unitset(unit_set)
                data = {"unitsetcontent": unit_set_choice}
            elif info_get_type == "modify":
                unit_set = UnitSet.objects.filter(
                    uuid=uuid, valid_flag=True).first()
                if not unit_set:
                    return make_get_error_response(message="单位集不存在")
                modify_serializer = UnitSetInfoModifySerializer(unit_set)
                data = modify_serializer.data
            else:
                unit_set = UnitSet.objects.filter(
                    uuid=uuid, valid_flag=True).first()
                if not unit_set:
                    return make_get_error_response(message="单位集不存在")
                info_serializer = UnitSetInfoSerializer(unit_set)
                data = info_serializer.data
            return make_get_success_response(data=data)
        except Exception as e:
            traceback.print_exc()
            return make_server_error_response(str(e))

    def put(self, request, uuid):
        res = {"code": 400, "message": "", "data": None}
        try:
            user_name = get_useraccount_from_request(request=request)
            user_name = get_user_from_useraccount(user_name)
            data = json.loads(request.body)
            unit_set = UnitSet.objects.filter(
                uuid=uuid, valid_flag=True).first()
            if not unit_set:
                return make_update_error_response(message="单位集不存在")
            modify_serializer = UnitSetInfoModifyInSerializer(
                data=data, instance=unit_set)
            if not modify_serializer.is_valid():
                res["code"] = 400
                res_message = "参数错误:\n"
                if "unit_set_name" in modify_serializer.errors:
                    res_message += "单位集中文名称已存在;\n"
                if "unit_set_name_en" in modify_serializer.errors:
                    res_message += "单位集英文名称已存在;\n"
                return make_update_error_response(message=res_message)
            data = modify_serializer.validated_data
            if "origin_unit_set" in data:
                data["origin_unit_set"] = UnitSet.objects.filter(
                    uuid=data["origin_unit_set"], valid_flag=True).first()
            if "unitsetcontent" in data:
                unitsetcontent_data = data.pop("unitsetcontent")
            else:
                unitsetcontent_data = []
            try:
                with transaction.atomic():
                    for field, value in data.items():
                        setattr(unit_set, field, value)
                    unit_set.modify_person = user_name
                    unit_set.save()
                    unit_set_content_list = UnitSetContent.objects.filter(
                        unit_set=unit_set)
                    for unit_set_content in unit_set_content_list:
                        unit_set_content.delete()
                    for content in unitsetcontent_data:
                        UnitSetContent.objects.create(
                            unit_set=unit_set,
                            quantity=Quantity.objects.filter(
                                uuid=content, valid_flag=True).first(),
                            unit=Unit.objects.filter(
                                uuid=unitsetcontent_data[content][-1], valid_flag=True).first(),
                        )
            except IntegrityError as e:
                return make_update_error_response(message=str(e))
            return make_update_success_response()
        except Exception as e:
            traceback.print_exc()
            return make_server_error_response(str(e))

    def delete(self, request, uuid):
        res = {"code": 400, "message": "", "data": None}
        try:
            user_name = get_useraccount_from_request(request=request)
            user_name = get_user_from_useraccount(user_name)
            unit_set = UnitSet.objects.filter(
                uuid=uuid, valid_flag=True).first()
            if not unit_set:
                return make_delete_error_response(message="单位集不存在")
            if unit_set.is_system:
                return make_delete_error_response(message="系统单位集不允许删除")
            try:
                with transaction.atomic():
                    unit_set.valid_flag = False
                    unit_set.modify_person = user_name
                    unit_set.save()
                    # 将该单位集作为原始单位集的单位集置空
                    unit_set_list = UnitSet.objects.filter(
                        origin_unit_set=unit_set)
                    for unit_set in unit_set_list:
                        unit_set.origin_unit_set = None
                        unit_set.save()
            except IntegrityError as e:
                return make_delete_error_response(message=str(e))
            return make_delete_success_response()
        except Exception as e:
            traceback.print_exc()
            return make_server_error_response(str(e))
